import call from './call.js'

const is = (tokens) => {
  return tokens.peek().type === 'keyword' && tokens.peek().value === 'if'
}

const parse = (tokens) => {
  const node = {
    type: 'IfStatement',
    body: []
  }

  const parseIf = (branchName) => {
    const _node = {
      test: {
        type: null,
        left: null,
        operator: null,
        right: null
      },
      consequent: {
        type: null,
        body: null
      }
    }

    if (tokens.peek().type !== 'keyword' || tokens.peek().value !== branchName) {
      tokens.croak(`Can't handle token: ${ tokens.peek().value }`)
    }

    tokens.next()

    if (branchName === 'if' || branchName === 'elif') {
      if (tokens.peek().type !== 'punctuation' || tokens.peek().value !== '(') {
        tokens.croak(`Can't handle token: ${ tokens.peek().value }`)
      }

      tokens.next()

      if (tokens.peek().type === 'identifier') {
        _node.test.left = {
          type: 'Identifier',
          name: tokens.peek().value
        }
      } else if (tokens.peek().type === 'number' || tokens.peek().type === 'literal') {
        _node.test.left = {
          type: 'Literal',
          value: tokens.peek().value
        }
      } else {
        tokens.croak(`Can't handle token: ${ tokens.peek().value }`)
      }

      tokens.next()

      if (tokens.peek().type === 'operator' && /^(>|<|>=|<=|==|!=)$/.test(tokens.peek().value)) {
        _node.test.type = 'BinaryExpression'
        _node.test.operator = tokens.peek().value
      } else {
        tokens.croak(`Can't handle token: ${ tokens.peek().value }`)
      }

      tokens.next()

      if (tokens.peek().type === 'identifier') {
        _node.test.right = {
          type: 'Identifier',
          name: tokens.peek().value
        }
      } else if (tokens.peek().type === 'number' || tokens.peek().type === 'literal') {
        _node.test.right = {
          type: 'Literal',
          value: tokens.peek().value
        }
      } else {
        tokens.croak(`Can't handle token: ${ tokens.peek().value }`)
      }

      tokens.next()

      if (tokens.peek().type !== 'punctuation' || tokens.peek().value !== ')') {
        tokens.croak(`Can't handle token: ${ tokens.peek().value }`)
      }

      tokens.next()

    } else {
      _node.test = null
    }

    if (tokens.peek().type !== 'operator' || tokens.peek().value !== '->') {
      tokens.croak(`Can't handle token: ${ tokens.peek().value }`)
    }

    tokens.next()

    if (tokens.peek().type === 'punctuation' && tokens.peek().value === '{') {
      tokens.next()

      _node.consequent.type = 'BlockStatement'
      _node.consequent.body = []

      let count = 0
      while (!(tokens.peek().type === 'punctuation' && tokens.peek().value === '}') || count > 0) {
        if (tokens.peek().type === 'punctuation' && tokens.peek().value === '{') {
          count++
        } else if (tokens.peek().type === 'punctuation' && tokens.peek().value === '}') {
          count--
        }
        _node.consequent.body.push(tokens.next())
      }

      tokens.next()
    } else if (tokens.peek().type === 'identifier') {
      _node.consequent.type = 'ExpressionStatement'
      _node.consequent.body = call.parse(tokens)
    } else {
      tokens.croak(`Can't handle token: ${ tokens.peek().value }`)
    }

    node.body.push(_node)

    if (tokens.eof()) return

    if (branchName === 'if' || branchName === 'elif') {
      if (tokens.peek().type === 'keyword' && tokens.peek().value === 'elif') {
        parseIf('elif')
      } else if (tokens.peek().type === 'keyword' && tokens.peek().value === 'else') {
        parseIf('else')
      }
    }
  }

  parseIf('if')

  return node
}

export default {
  is,
  parse
}